#ifndef FRAMEBASE_H
#define FRAMEBASE_H

#define CAN_CRC_DIVISOR 0B1100010110011001      // CAN的CRC的除数

#include <stdint.h>

typedef unsigned int canU32_t;
typedef unsigned char canU8_t;
typedef unsigned short canU16_t;
typedef unsigned long long canU64_t;

void setBit(canU8_t* Data, canU32_t data, const canU8_t dataBits, const canU8_t offset);
canU64_t getBit(const canU8_t* Data,const canU8_t dataBits, const canU8_t offset);

#define set_bit(REG, BIT)     ((REG) |= (BIT))
#define clear_bit(REG, BIT)   ((REG) &= ~(BIT))
#define read_bit(REG, BIT)    ((REG) & (BIT))
#define set_frame_bit(DATA,MASK,MOVE)   (((MASK >> MOVE) & (DATA)) << MOVE)

/*
 * canLevel
 * CAN的电平信号：显性，隐性
 */
enum canLevel{
    Dominance = 0,
    Recessive = 1
};

/*
 * CanData
 * Can一次能发送的最大字节数8。
 */
union FrameData{
    int dataInt[2];
    float dataFloat[2];
    double dataDouble;
    canU8_t dataU8[8];
};


union CanFrame{
    canU8_t dataU8[20];
    canU16_t dataU16[10];
    canU32_t dataU32[5];
    canU64_t dataU64[2];
};

/*
 * @FrameSize
 *  帧大小类型：标准帧，扩展格式帧
 */
enum FrameSize{
    Standard,
    Expanded,
    stCRCBitsBase = 19,
    exCRCBitsBase = 39
};

/*
 * @FrameType
 *  帧类型：数据帧，远程帧，错误帧，过载帧，帧间隔
 * */
enum FrameType{
    TypeData,
    TypeRequest,
    TypeError,
    TypeOverload,
    TypeBetween
};

/*
 * 标准帧格式和扩展帧格式的各个功能位的偏移
 * */
enum DataMOVE{
    //
    Data_LEN = 8,
    /**------- 扩展数据帧 --------**/
    eSOF_MOVE = 0,
    eStdId_MOVE = 1,
    eSRR_MOVE = 12,
    eIDE_MOVE = 13,
    eExtId_MOVE = 14,

    eRTR_MOVE = 32,
    eR1_MOVE = 33,
    eR0_MOVE = 34,
    eDLC_MOVE = 35,

    eData0_MOVE = 39,   // 由于data长度不一定，后续的偏移应该 是 #偏移 + DLC * Data_LEN

    eCRC_MOVE = 39,
    eCRC_Q_MOVE = 54,
    eACK_MOVE = 55,
    eACK_Q_MOVE = 56,
    eEOF_MOVE = 57,

    /**------- 标准数据帧 --------**/
    sSOF_MOVE = 0,
    sStdId_MOVE = 1,
    sRTR_MOVE = 12,
    sIDE_MOVE = 13,
    sR0_MOVE = 14,
    sDLC_MOVE = 15,

    sData0_MOVE = 19,

    sCRC_MOVE = 19,
    sCRC_Q_MOVE = 34,
    sACK_MOVE = 35,
    sACK_Q_MOVE = 36,
    sEOF_MOVE = 37,

};

/*
 * CANError
 * CAN错误类型
 * */
enum CANError{
    NoError,
    FormatError,              // 数据帧格式错误（帧格式不符合任意一种帧格式）
    CRCError,                 // CRC校验错误
    ACKError,                 // 无应答错误
    BitStuffingError,         // 位填充错误（数据违反位填充规则）
    BitSendError,             // 位发送错误（总线电平和发送电平不相符，需要硬件检测，软件无法单独发现此错误）
};

class CAN_FrameBase{
public:
    const canLevel SOF = Dominance;     // 起始位为0
    canU16_t StdId;                     // 节点 ID 的低 11 位
    canLevel SRR;     // 代替标准帧请求位，在扩展帧中为始终为0
    canLevel IDE;                       // 指定 标准帧 或者 扩展帧 标准帧:0 扩展帧:1
    canU32_t ExtId;                     // 节点 ID 的高 18 位
    canLevel RTR;                       // 指定 远程帧 或者 数据帧 数据帧:0 远程帧:1
    const canLevel r1 = Dominance;      // 保留位1为 0
    const canLevel r0 = Dominance;      // 保留位0为 0
    canU8_t DLC;                        // 数据长度
    canU32_t Data[2];                       // 数据段 8 字节
    canU16_t CRC_15;                       // 低15位的CRC校验
    const canLevel CRC_Q = Recessive;   // CRC界定符
    canLevel ACK;                       // ACK位,发送节点:发送隐型电平，接收端接收正确的结果:发送显性电平
    const canLevel ACK_Q = Recessive;   // ACK_Q位界定符
    const canU8_t _EOF = 0XFF;           // 7位的EOF标志
};







#endif // FRAMEBASE_H
